#pragma once

#include "Point.h";

#include "Vector.h";

#include "Flatness.h";

template <typename T2> class Triangle
{
	public:
		Triangle(Point<T2> i_A, Point<T2> i_B, Point<T2> i_C);
		bool IfPointInside(Point<T2>& i_point);
		bool IfIntersectOther(Triangle<T2>& i_triangle);
	private:
		Point<T2> m_A;
		Point<T2> m_B;
		Point<T2> m_C;
};




template <typename T2> Triangle<T2>::Triangle(Point<T2> i_A, Point<T2> i_B, Point<T2> i_C)
{
	m_A=i_A;
	m_B=i_B;
	m_C=i_C;
};

template <typename T2> bool Triangle<T2>::IfIntersectOther(Triangle<T2>& i_triangle)
{
	Flatness<T2> temp1 (m_A,m_B,m_C);
	Flatness<T2> temp2 (i_triangle.m_A,i_triangle.m_B,i_triangle.m_C);
	if(temp1.m_a==temp2.m_a && temp1.m_b==temp2.m_b && temp1.m_c==temp2.m_c)
	{
		if(temp1.m_d!=temp2.m_d)
			return false;
		else
		{
			if(IfPointInside(i_triangle.m_A) || IfPointInside(i_triangle.m_B) 
				|| IfPointInside(i_triangle.m_C))
				return true;
			else
				return false;
		}
	}
	double a=temp1.m_a,b=temp1.m_b,c=temp1.m_b,d=temp1.m_d;
	double a1,b1,c1,a2,b2,c2;
	for(int i=1;i<4;i++)
	{
		Point<T2> help;
		if(i==1)
		{
			a1=double(1)/(i_triangle.m_B.m_x-i_triangle.m_A.m_x);
			b1=double(-1)/(i_triangle.m_B.m_y-i_triangle.m_A.m_y);
			c1=double(i_triangle.m_A.m_y)/(i_triangle.m_B.m_y-i_triangle.m_A.m_y)-
				double(i_triangle.m_A.m_x)/(i_triangle.m_B.m_x-i_triangle.m_A.m_x);
			a2=double(1)/(i_triangle.m_B.m_x-i_triangle.m_A.m_x);
			b2=double(-1)/(i_triangle.m_B.m_z-i_triangle.m_A.m_z);
			c2=double(i_triangle.m_A.m_z)/(i_triangle.m_B.m_z-i_triangle.m_A.m_z)-
				double(i_triangle.m_A.m_x)/(i_triangle.m_B.m_x-i_triangle.m_A.m_x);
		}
		if(i==2)
		{
			a1=double(1)/(i_triangle.m_C.m_x-i_triangle.m_A.m_x);
			b1=double(-1)/(i_triangle.m_C.m_y-i_triangle.m_A.m_y);
			c1=double(i_triangle.m_A.m_y)/(i_triangle.m_C.m_y-i_triangle.m_A.m_y)-
				double(i_triangle.m_A.m_x)/(i_triangle.m_C.m_x-i_triangle.m_A.m_x);
			a2=double(1)/(i_triangle.m_C.m_x-i_triangle.m_A.m_x);
			b2=double(-1)/(i_triangle.m_C.m_z-i_triangle.m_A.m_z);
			c2=double(i_triangle.m_A.m_z)/(i_triangle.m_C.m_z-i_triangle.m_A.m_z)-
				double(i_triangle.m_A.m_x)/(i_triangle.m_C.m_x-i_triangle.m_A.m_x);
		}
		if(i==3)
		{
			a1=double(1)/(i_triangle.m_B.m_x-i_triangle.m_C.m_x);
			b1=double(-1)/(i_triangle.m_B.m_y-i_triangle.m_C.m_y);
			c1=double(i_triangle.m_C.m_y)/(i_triangle.m_B.m_y-i_triangle.m_C.m_y)-
				double(i_triangle.m_C.m_x)/(i_triangle.m_B.m_x-i_triangle.m_C.m_x);
			a2=double(1)/(i_triangle.m_B.m_x-i_triangle.m_C.m_x);
			b2=double(-1)/(i_triangle.m_B.m_z-i_triangle.m_C.m_z);
			c2=double(i_triangle.m_C.m_z)/(i_triangle.m_B.m_z-i_triangle.m_C.m_z)-
				double(i_triangle.m_C.m_x)/(i_triangle.m_B.m_x-i_triangle.m_C.m_x);
		}
		double k=-b/(a*a*c) + b1/(a1*a*c);
		double m=-d/(a*a*c) + c1/(a1*a*c);
	    help.m_y=((-a2*c*m)/a + b2*m + c2 - (a2*d)/a)/((a2*c*k)/a + (a2*b)/a - b2*k);
		help.m_z=k*help.m_y + m;
		help.m_x=(1/a) * (-b*help.m_y - c*help.m_z - d); 
		if(IfPointInside(help))
			return true;
	}
	return false;
};

template <typename T2> bool Triangle<T2>::IfPointInside(Point<T2>& i_point)
{
	Flatness<T2> temp(m_A,m_B,m_C);
	if (temp.PointDeviation(i_point)!=0)
		return false;
	Vector<T2> A_f(m_A,m_B);
	Vector<T2> B_f=-A_f;
	Vector<T2> A_s(m_A,m_C);
	Vector<T2> C_f=-A_s;
	Vector<T2> B_s(m_B,m_C);
	Vector<T2> C_s=-B_s;
	Vector<T2> xA(m_A,i_point);
	Vector<T2> xB(m_B,i_point);
	Vector<T2> xC(m_C,i_point);
	if( ((xA^A_f) * (xA^A_s) <=0) && ((xB^B_f) * (xB^B_s) <=0) &&  ((xC^C_f) * (xC^C_s) <=0) ) 
		return true;
	return false;
};